package com.leyou.item.service;

import com.leyou.common.exception.LyException;
import com.leyou.common.exception.enums.ExceptionEnum;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.dto.SpecGroupDTO;
import com.leyou.item.entity.SpecGroup;
import com.leyou.item.entity.SpecParam;
import com.leyou.item.mapper.SpecGroupMapper;
import com.leyou.item.mapper.SpecParamMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.MalformedParameterizedTypeException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LT
 * @version 1.0.0
 * @ClassName SpecService.java
 * @Description TODO 规格服务类
 * @createTime 2020年05月06日 17:17:00
 */
@Service
@Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.DEFAULT
)
public class SpecService {

    @Autowired
    private SpecGroupMapper groupMapper;

    @Autowired
    private SpecParamMapper paramMapper;

    /**
     * 查询规格参数：多个条件
     *
     * @param gid       规格组的id
     * @param cid       分类的id
     * @param searching 是否是搜索过滤参数
     * @return
     */
    public List<SpecParam> findSpecParams(Long gid, Long cid, Boolean searching) {
        // 假如cid和gid都不传，就认为参数有误.
        if (gid == null && cid == null) {
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }

        // 封装条件
        SpecParam specParam = new SpecParam();
        specParam.setGroupId(gid);
        specParam.setCid(cid);
        specParam.setSearching(searching);

        // 数据库查询
        List<SpecParam> specParams = paramMapper.select(specParam);
        if (CollectionUtils.isEmpty(specParams)) {
            throw new LyException(ExceptionEnum.SPEC_NOT_FOUND);
        }
        return specParams;
    }

    /**
     * 根据分类id查询规格组
     *
     * @param id 分类的id
     * @return 规格组列表
     */
    public List<SpecGroup> findSpecGroupsByCid(Long id) {
        // 封装条件
        SpecGroup specGroup = new SpecGroup();
        specGroup.setCid(id);
        // 数据库查询
        List<SpecGroup> specGroups = groupMapper.select(specGroup);
        // 判空
        if (CollectionUtils.isEmpty(specGroups)) {
            throw new LyException(ExceptionEnum.SPEC_NOT_FOUND);
        }
        return specGroups;
    }

    /**
     * 根据categoryId查询规格参数组和组内参数(根据第三级分类id查询规格组和组内参数)
     *
     * @param cid
     * @return
     */
    public List<SpecGroupDTO> findSpecGroupByCid(Long cid) {
        // 根据分类id查询组
        List<SpecGroup> specGroupList = findSpecGroupsByCid(cid);
        // 转成DTO
        List<SpecGroupDTO> specGroupDTOList = BeanHelper.copyWithCollection(specGroupList, SpecGroupDTO.class);

        // 查询规格参数的方式三：通过分类id一次性查询出来 【高级】 ：  只有两条
        List<SpecParam> specParams = findSpecParams(null, cid, null);
        // 使用jdk1.8的流的特性： 分组  :  返回的是map  ：  key： groupId规格组的id  ， value:  规格参数list集合
        Map<Long, List<SpecParam>> specMap = specParams.stream().collect(Collectors.groupingBy(SpecParam::getGroupId));
        // 迭代组
        for (SpecGroupDTO specGroupDTO : specGroupDTOList) {
            specGroupDTO.setParams(specMap.get(specGroupDTO.getId()));
        }


        // 查询规格参数的方式二：通过分类id一次性查询出来 【中级】 ：  只有两条查询
        // List<SpecParam> specParams = findSpecParams(null, cid, null);
        // // 第一层for循环先迭代组
        // for (SpecGroupDTO specGroupDTO : specGroupDTOList) {
        //     // 第二层for循环： 规格参数：  通过规格参数的组id和groupDTO的id做对比
        //     for (SpecParam specParam : specParams) {
        //         if (specParam.getGroupId().equals(specGroupDTO.getId())) {
        //             // 如果进入这里，说明规格参数属于这个规格组
        //             if (specGroupDTO.getParams() == null) {
        //                 specGroupDTO.setParams(new ArrayList<SpecParam>());
        //             }
        //             specGroupDTO.getParams().add(specParam);
        //         }
        //     }
        // }

        // 查询规格参数的方式一： 根据组的id查询规格参数 : 入门级写法： 在for循环操作数据库  ：  一堆sql
        // for (SpecGroupDTO specGroupDTO : specGroupDTOList) {
        //     List<SpecParam> specParams = findSpecParams(specGroupDTO.getId(), null, null);
        //     specGroupDTO.setParams(specParams);
        // }

        // 返回specGroupDTOList
        return specGroupDTOList;
    }
}
